/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * GamePanel.java
 *
 * Created on 13-févr.-2009, 0:36:08
 */

package GUI;

import Actors.Actor;
import Controller.EnigmaController;
import Controller.MouseMovedCommand;
import Controller.ScrollInventoryCommand;
import Controller.UseActiveItemCommand;
import Model.ActorEvent;
import Model.ActorManagerListener;
import Model.Case;
import Model.CaseEvent;
import Model.GameStateListener;
import Model.PlateauListener;
import Model.PlayerBallListener;
import java.awt.AWTException;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.awt.image.MemoryImageSource;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Snowangelic
 */
public class GamePanel extends javax.swing.JPanel implements 
        MouseListener, MouseMotionListener, KeyListener,PlateauListener, ActorManagerListener,GameStateListener, PlayerBallListener{
    
    EnigmaGUIMainWindow mainInterface;
    EnigmaController controller;
    Layer floorLayer;
    Layer itemLayer;
    Vector<Layer> actorsLayer;
    Layer stoneLayer;
    Layer informationLayer;

    Case[][] caseArray;
    CaseView[][] caseViewArray;
    ArrayList<ActorView> actorViewArray;

    GameStateView gameStateView;
    int gameState=0;

    private int mouseX;
    private int mouseY;

    int xOffset;
    int yOffset;

    Robot mouseMover;
    
    /** Creates new form GamePanel */
    public GamePanel() {
        try {
            mouseMover = new Robot();
        } catch (AWTException ex) {
            Logger.getLogger(EnigmaGUIMainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }

        initComponents();

        xOffset=0;
        yOffset=0;
        caseViewArray=new CaseView[20][13];
        actorViewArray=new ArrayList<ActorView>();

        setFocusable(true);
        addMouseMotionListener(this);
        addMouseListener(this);
        addKeyListener(this);


        stoneLayer = new Layer();
        floorLayer = new Layer();
        itemLayer = new Layer();
        actorsLayer = new Vector<Layer>();
        informationLayer=new Layer();
        gameStateView=new GameStateView(informationLayer);
        //mainInterface=main;

        this.setSize(640,480);
        this.setVisible(true);
        
    }

    void setActorLayer(BufferedImage actorImage) {
        //actorLayer=actorImage;
    }

    void setMainWindow(EnigmaGUIMainWindow main){
        mainInterface=main;
    }

    void setController(EnigmaController controller){
        this.controller=controller;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setMaximumSize(new java.awt.Dimension(640, 416));
        setMinimumSize(new java.awt.Dimension(640, 416));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 731, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 528, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

     @Override
    public void paintComponent(Graphics g){

        for(Layer actorLayer : actorsLayer)
            updateLayer(actorLayer);
        updateLayer(floorLayer);
        updateLayer(itemLayer);
        updateLayer(stoneLayer);
        updateLayer(informationLayer);
        //if(informationLayerUpdateNeeded)mainInterface.updateInformationLayer();

        super.paintComponent(g);

        BufferedImage bufferImage = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
        Graphics buffer = bufferImage.getGraphics();
        buffer.drawImage(floorLayer.getImage(), 0, 0, null);
        buffer.drawImage(itemLayer.getImage(), 0, 0, null);
        try{
            for(Layer actorLayer : actorsLayer)
                buffer.drawImage(actorLayer.getImage(), 0, 0, null);
        }
        catch(ConcurrentModificationException e){}
        buffer.drawImage(stoneLayer.getImage(), 0, 0, null);
        buffer.drawImage(informationLayer.getImage(), 0, 0, null);
        g.drawImage(bufferImage, 0, 0, this);
         
     }

     private void updateLayer(Layer layer){
         layer.updateLayer();
     }
   
    public void caseAdded(CaseEvent e) {
        caseArray[e.getSource().getXIndex()][e.getSource().getYIndex()]=e.getSource();
        if(e.getSource().getXIndex()<20 && e.getSource().getYIndex()<13){
            CaseView newCaseView=new CaseView(e.getSource().getXIndex()*32,
                    e.getSource().getYIndex()*32,floorLayer,itemLayer,stoneLayer);

            e.getSource().addListener(newCaseView);
            caseViewArray[e.getSource().getXIndex()][e.getSource().getYIndex()]=newCaseView;
        }
    }

    public void changeOffset(int newXOffset,int newYOffset){
        for(int i=0;i<20;i++){
            for(int j=0;j<13;j++){
                caseArray[xOffset+i][yOffset+j].removeListener(caseViewArray[i][j]);
                caseArray[newXOffset+i][newYOffset+j].addListener(caseViewArray[i][j]);
            }
        }

        for(ActorView viewer : actorViewArray)
            viewer.setOffset(newXOffset*32,newYOffset*32);

        xOffset=newXOffset;
        yOffset=newYOffset;
    }

    public void actorAdded(ActorEvent e) {
        Actor a=e.getSource();
        Layer myNewLayer=new ActorLayer();
        ActorView myNewActorView=new ActorView(myNewLayer);
        actorViewArray.add(myNewActorView);
        actorsLayer.add(myNewLayer);

        a.addListener(myNewActorView);
    }

    public void gameStateChanged(int newGameState) {
        gameState=newGameState;
        if(newGameState==1){
            mouseMover.mouseMove(this.getX()+mainInterface.getX()+320,this.getY()+mainInterface.getY()+240);
            hideMouse();
        }
        else showMouse();
        gameStateView.gameStateChanged(newGameState);
    }
  
    public void mouseDragged(MouseEvent e) {
    }

    public void mouseMoved(MouseEvent e) {
        if(e.getX()!=321 || e.getY()!=298)
            if(e.getX()!=320 || e.getY()!=240){
                if(controller!=null)controller.mouseMoved(new MouseMovedCommand(e.getX()-320,e.getY()-240,this));
                if(gameState==1)mouseMover.mouseMove(this.getX()+mainInterface.getX()+320,this.getY()+mainInterface.getY()+240);
            }
    }

    public void mouseClicked(MouseEvent e) {
    }

    private void hideMouse(){
        
        //--- Adieu souris ---
        int[] pixels = new int[16 * 16];
        Image cursorImage = Toolkit.getDefaultToolkit().createImage(
        new MemoryImageSource(16, 16, pixels, 0, 16));
        Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor
        (cursorImage, new Point(0, 0), "Transparent");
        setCursor(transparentCursor);
        // ---
         
    }

    private void showMouse(){
        setCursor( new Cursor( Cursor.DEFAULT_CURSOR ) );
    }

    public void mousePressed(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON1)
            controller.useActiveItem(new UseActiveItemCommand(this));
        else if (e.getButton() == MouseEvent.BUTTON3)
            controller.scrollInventory(new ScrollInventoryCommand(this));
    }

    public void mouseReleased(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseEntered(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseExited(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
        //if(e.getKeyCode()==32) mainInterface.pauseGame();
        controller.keyPressed(e.getKeyCode());
    }

    public void keyReleased(KeyEvent e) {
    }

    public void dimensionSet(int width, int height) {
        caseArray=new Case[width][height];
    }

    public void ballMoved(ActorEvent e) {
        int newXOffset=xOffset;
        int newYOffset=yOffset;

        if(e.getSource().getX() > (xOffset+20)*32){
            if(xOffset+40 < caseArray.length) newXOffset=xOffset+20;
            else newXOffset=caseArray.length - 20;
        }
        else if(e.getSource().getX() < (xOffset)*32){
            if(xOffset-20 >= 0) newXOffset=xOffset-20;
            else newXOffset=0;
        }

        if(e.getSource().getY() > (yOffset+13)*32){
            if(yOffset+25 < caseArray[0].length) newYOffset=yOffset+13;
            else newYOffset=caseArray[0].length - 13;
        }
        else if(e.getSource().getY() < (yOffset)*32){
            if(yOffset-13 >= 0) newYOffset=yOffset-13;
            else newYOffset=0;
        }

        if(xOffset != newXOffset || yOffset != newYOffset)
            changeOffset(newXOffset,newYOffset);
    }

    public void playerKilled(ActorEvent e) {
    }

}
